﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

using System.Collections.ObjectModel;

namespace Mystery.SharePoint
{
	/// <summary>
	/// Extension methods for SPWeb
	/// </summary>
	public static class SPWebExtensions
	{
		private const string FriendlyTemplateNameKey = "SPM.Template";
				
		/// <summary>
		/// Gives the specified principal the speficifed role permissions to the web.
		/// Breaks inheritance if necessary. 
		/// </summary>
		/// <param name="web">The web to change permissions for</param>
		/// <param name="principal">The principal we are setting the permissions for</param>
		/// <param name="role">The role that represents the permissions the principal receives.</param>
		public static void SetPermission(this SPWeb web, SPPrincipal principal, SPRoleType role)
		{
			if (web == null) throw new ArgumentNullException("web");
			if (principal == null) throw new ArgumentNullException("principal");

			if (web.HasUniqueRoleAssignments == false)
			{
				web.BreakRoleInheritance(false);
			}

			SPRoleAssignment assignment = new SPRoleAssignment(principal);
			SPRoleDefinition definition = web.RoleDefinitions.GetByType(role);

			assignment.RoleDefinitionBindings.Add(definition);
			web.RoleAssignments.Add(assignment);
		}

		/// <summary>
		/// Sets the master pages for the web.
		/// </summary>
		/// <param name="web"></param>
		/// <param name="masterPage">The name of the master page. I.e. mystery.master</param>
		/// <param name="customMasterPage">The name of the custom master page. I.e. mystery.master</param>
		/// <returns>True if the web was updated</returns>
		public static bool SetMasterPages(this SPWeb web, string masterPage, string customMasterPage)
		{
			if (web == null) throw new ArgumentNullException("web");
			if (string.IsNullOrEmpty(masterPage) == true) throw new ArgumentNullException("masterPage");
			if (string.IsNullOrEmpty(customMasterPage) == true) throw new ArgumentNullException("customMasterPage");

			string url = web.Site.ServerRelativeUrl;
			string masterUrl = web.MasterUrl;
			string customUrl = web.CustomMasterUrl;
			bool updated = false;

			if (url.EndsWith("/", StringComparison.OrdinalIgnoreCase) == true)
			{
				masterUrl = url + "_catalogs/masterpage/" + masterPage;
				customUrl = url + "_catalogs/masterpage/" + customMasterPage;
			}
			else
			{
				masterUrl = url + "/_catalogs/masterpage/" + masterPage;
				customUrl = url + "/_catalogs/masterpage/" + customMasterPage;
			}

			if (web.MasterUrl.Equals(masterUrl, StringComparison.InvariantCultureIgnoreCase) == false)
			{
				web.MasterUrl = masterUrl;
				updated = true;
			}
			if (web.CustomMasterUrl.Equals(customUrl, StringComparison.InvariantCultureIgnoreCase) == false)
			{
				web.CustomMasterUrl = customUrl;
				updated = true;
			}

			return updated;
		}

		/// <summary>
		/// Sets a friendly template name
		/// </summary>
		/// <param name="web"></param>
		/// <param name="templateId">A string representing the type of site. This will be used to match an entry in the ApplicationType_XYZ.xml file</param>
		/// <returns>True if the site property bag needs to be updated. Leaving the control to the calling function allows the caller to control the number of updates</returns>
		public static bool SetFriendlyTemplateName(this SPWeb web, string templateId)
		{
			if (web == null) throw new ArgumentNullException("web");
			string t = SPUtility.GetLocalizedString(templateId, "core", web.Language);
            return web.Properties.Write(FriendlyTemplateNameKey, t);
		}
		/// <summary>
		/// Gets the friendly template name
		/// </summary>
		/// <param name="web"></param>
		/// <returns>A string representing the template. This can be used to find information in the ApplicationType_XYZ.xml file</returns>
		public static string GetFriendlyTemplateName(this SPWeb web)
		{
			if (web == null) throw new ArgumentNullException("web");

			// defaults to the standard SharePoint id
			string templateId = web.WebTemplate + "#" + web.Configuration;
            return web.Properties.Read(FriendlyTemplateNameKey, templateId);
		}
		/// <summary>
		/// Sets the available web templates.
		/// </summary>
		/// <param name="web"></param>
		/// <param name="templates">The list over templates to set</param>
		/// <returns>True if web was updated, otherwise false</returns>
		public static bool SetAvailableWebTemplates(this SPWeb web, string[] templates)
		{
			if (web == null) throw new ArgumentNullException("web");

			if ((templates == null) ||
				(templates.Length == 0))
			{
				return false;
			}
			Collection<SPWebTemplate> webTemplates = new Collection<SPWebTemplate>();

			foreach (SPWebTemplate template in web.GetAvailableWebTemplates(web.Language))
			{
				if (templates.Contains(template.Name) == true)
				{
					webTemplates.Add(template);
				}
			}
			web.SetAvailableWebTemplates(webTemplates, web.Language);
			return true;
		}
        /// <summary>
        /// Creates an object based on the value of a property string
        /// </summary>
        /// <typeparam name="T">Type of object to return</typeparam>
        /// <param name="web"></param>
        /// <param name="key">The key representing the full name of the object</param>
        /// <returns>An object of the specified type</returns>
        public static T CreateObjectFromPropertyString<T>(this SPWeb web, string key) where T : class
        {
            string v = web.Properties.Read(key, string.Empty);
            if (v != string.Empty)
            {
                return ProvisioningUtilities.CreateObjectFromString<T>(v);
            }
            return null;
        }
        /// <summary>
        /// Creates an object based on the value of a property string
        /// </summary>
        /// <typeparam name="T">Type of object to return</typeparam>
        /// <param name="web"></param>
        /// <param name="key">The key representing the full name of the object</param>
        /// <param name="args">Argumenst to pass to the object contstructor</param>
        /// <returns>An object of the specified type</returns>
        public static T CreateObjectFromPropertyString<T>(this SPWeb web, string key, params object[] args) where T : class
        {
            string v = web.Properties.Read(key, string.Empty);
            if (v != string.Empty)
            {
                return ProvisioningUtilities.CreateObjectFromString<T>(v, args);
            }
            return null;
        }

        /// <summary>
        /// Sets the value of a property on the root web
        /// </summary>
        /// <param name="site"></param>
        /// <param name="key">Name of property</param>
        /// <param name="value">Value of property</param>
        /// <returns>True if property bag was updated</returns>
        public static bool SetLocalizableProperty(this SPWeb web, string key, string value)
        {
            if (web == null) throw new ArgumentNullException("web");
            if (string.IsNullOrEmpty(value) == true) throw new ArgumentNullException("value");

            string t = SPUtility.GetLocalizedString(value, "core", web.Language);

            return web.Properties.Write(key, t);
        }
        /// <summary>
        /// Provisions the set of standard lists such as Shared Documents, Announcements, Calendar, etc
        /// </summary>
        /// <param name="web"></param>
        public static void ProvisionStandardLists(this SPWeb web)
        {
            if (web == null) throw new ArgumentNullException("web");

            web.Lists.Provision(
                "$Resources:core,shareddocuments_Title;",
                "",
                "$Resources:core,shareddocuments_Folder;",
                "00BFEA71-E717-4E80-AA17-D0C71B360101",
                SPListTemplateType.DocumentLibrary,
                "101",
                SPListTemplate.QuickLaunchOptions.On);

            web.Lists.Provision(
                "$Resources:core,discussions_Title;",
                "",
                "$Resources:core,lists_Folder;/$Resources:core,discussions_Folder;",
                "00BFEA71-6A49-43FA-B535-D15C05500108",
                SPListTemplateType.DiscussionBoard,
                "",
                SPListTemplate.QuickLaunchOptions.On);

            web.Lists.Provision(
                "$Resources:core,announceList;",
                "",
                "$Resources:core,lists_Folder;/$Resources:core,announce_Folder;",
                "00BFEA71-D1CE-42de-9C63-A44004CE0104",
                SPListTemplateType.Announcements,
                "",
                SPListTemplate.QuickLaunchOptions.On);

            web.Lists.Provision(
               "$Resources:core,linksList;",
               "",
               "$Resources:core,lists_Folder;/$Resources:core,links_Folder;",
               "00BFEA71-2062-426C-90BF-714C59600103",
               SPListTemplateType.Links,
               "",
               SPListTemplate.QuickLaunchOptions.On);

            web.Lists.Provision(
              "$Resources:core,calendarList;",
              "",
              "$Resources:core,lists_Folder;/$Resources:core,calendar_Folder;",
              "00BFEA71-EC85-4903-972D-EBE475780106",
              SPListTemplateType.Events,
              "",
              SPListTemplate.QuickLaunchOptions.On);

            web.Lists.Provision(
              "$Resources:core,taskList;",
              "",
              "$Resources:core,lists_Folder;/$Resources:core,tasks_Folder;",
              "00BFEA71-A83E-497E-9BA0-7A5C597D0107",
              SPListTemplateType.Tasks,
              "",
              SPListTemplate.QuickLaunchOptions.On);
        }
	}
}
